Türkçe

Katı değer kısıtlamaları uygulamak, kod netliğini artırmak ve hataları önlemek için güçlü bir özellik olan TypeScript literal tiplerini keşfedin. Pratik örnekler ve gelişmiş tekniklerle öğrenin.

TypeScript Literal Tipleri: Kesin Değer Kısıtlamalarında Uzmanlaşma

JavaScript'in bir üst kümesi olan TypeScript, web geliştirmenin dinamik dünyasına statik tipleme getirir. En güçlü özelliklerinden biri literal tipler kavramıdır. Literal tipler, bir değişkenin veya özelliğin alabileceği kesin değeri belirtmenize olanak tanıyarak gelişmiş tip güvenliği sağlar ve beklenmedik hataları önler. Bu makale, literal tipleri sözdizimi, kullanımı ve pratik örneklerle faydalarını kapsayarak derinlemesine inceleyecektir.

Literal Tipler Nedir?

string, number veya boolean gibi geleneksel tiplerin aksine, literal tipler geniş bir değer kategorisini temsil etmez. Bunun yerine, belirli, sabit değerleri temsil ederler. TypeScript üç tür literal tipi destekler:

Literal tipleri kullanarak, verilerinizin gerçek kısıtlamalarını yansıtan daha kesin tip tanımları oluşturabilir, bu da daha sağlam ve sürdürülebilir kod yazmanızı sağlar.

String Literal Tipleri

String literal tipleri, en sık kullanılan literal tipidir. Bir değişkenin veya özelliğin yalnızca önceden tanımlanmış bir dizi dize değerinden birini tutabileceğini belirtmenize olanak tanır.

Temel Sözdizimi

Bir string literal tipi tanımlamanın sözdizimi basittir:


type IzinVerilenDegerler = "deger1" | "deger2" | "deger3";

Bu, yalnızca "deger1", "deger2" veya "deger3" string'lerini tutabilen IzinVerilenDegerler adında bir tip tanımlar.

Pratik Örnekler

1. Bir Renk Paleti Tanımlama:

Bir kullanıcı arayüzü kütüphanesi oluşturduğunuzu ve kullanıcıların yalnızca önceden tanımlanmış bir paletten renk belirtebildiğinden emin olmak istediğinizi hayal edin:


type Renk = "red" | "green" | "blue" | "yellow";

function ogeyiBoya(element: HTMLElement, color: Renk) {
  element.style.backgroundColor = color;
}

ogeyiBoya(document.getElementById("myElement")!, "red"); // Geçerli
ogeyiBoya(document.getElementById("myElement")!, "purple"); // Hata: '"purple"' türündeki argüman, 'Renk' türündeki parametreye atanamaz.

Bu örnek, string literal tiplerinin nasıl izin verilen katı bir değer kümesini zorunlu kılabileceğini ve geliştiricilerin yanlışlıkla geçersiz renkler kullanmasını nasıl önlediğini göstermektedir.

2. API Uç Noktalarını Tanımlama:

API'lerle çalışırken, genellikle izin verilen uç noktaları belirtmeniz gerekir. String literal tipleri bunu zorunlu kılmanıza yardımcı olabilir:


type APIUcNoktasi = "/users" | "/posts" | "/comments";

function veriCek(endpoint: APIUcNoktasi) {
  // ... belirtilen uç noktadan veri çekme uygulaması
  console.log(`${endpoint} adresinden veri çekiliyor`);
}

veriCek("/users"); // Geçerli
veriCek("/products"); // Hata: '"/products"' türündeki argüman, 'APIUcNoktasi' türündeki parametreye atanamaz.

Bu örnek, veriCek fonksiyonunun yalnızca geçerli API uç noktalarıyla çağrılabilmesini sağlar, bu da yazım hatalarından veya yanlış uç nokta adlarından kaynaklanan hata riskini azaltır.

3. Farklı Dilleri Ele Alma (Uluslararasılaştırma - i18n):

Küresel uygulamalarda, farklı dilleri ele almanız gerekebilir. Uygulamanızın yalnızca belirtilen dilleri desteklediğinden emin olmak için string literal tiplerini kullanabilirsiniz:


type Dil = "en" | "es" | "fr" | "de" | "zh";

function cevir(text: string, language: Dil): string {
  // ... metni belirtilen dile çevirme uygulaması
  console.log(`'${text}' metni ${language} diline çevriliyor`);
  return "Çevrilmiş metin"; // Yer tutucu
}

cevir("Hello", "en"); // Geçerli
cevir("Hello", "ja"); // Hata: '"ja"' türündeki argüman, 'Dil' türündeki parametreye atanamaz.

Bu örnek, uygulamanızda yalnızca desteklenen dillerin kullanılmasını nasıl sağlayacağınızı gösterir.

Sayı Literal Tipleri

Sayı literal tipleri, bir değişkenin veya özelliğin yalnızca belirli bir sayısal değeri tutabileceğini belirtmenize olanak tanır.

Temel Sözdizimi

Sayı literal tipi tanımlamanın sözdizimi, string literal tiplerine benzer:


type DurumKodu = 200 | 404 | 500;

Bu, yalnızca 200, 404 veya 500 sayılarını tutabilen DurumKodu adında bir tip tanımlar.

Pratik Örnekler

1. HTTP Durum Kodlarını Tanımlama:

HTTP durum kodlarını temsil etmek için sayı literal tiplerini kullanabilir ve uygulamanızda yalnızca geçerli kodların kullanılmasını sağlayabilirsiniz:


type HTTPDurum = 200 | 400 | 401 | 403 | 404 | 500;

function yanitiIsle(status: HTTPDurum) {
  switch (status) {
    case 200:
      console.log("Başarılı!");
      break;
    case 400:
      console.log("Geçersiz İstek");
      break;
    // ... diğer durumlar
    default:
      console.log("Bilinmeyen Durum");
  }
}

yanitiIsle(200); // Geçerli
yanitiIsle(600); // Hata: '600' türündeki argüman, 'HTTPDurum' türündeki parametreye atanamaz.

Bu örnek, geçerli HTTP durum kodlarının kullanımını zorunlu kılarak yanlış veya standart dışı kodların kullanılmasından kaynaklanan hataları önler.

2. Sabit Seçenekleri Temsil Etme:

Bir yapılandırma nesnesindeki sabit seçenekleri temsil etmek için sayı literal tiplerini kullanabilirsiniz:


type YenidenDenemeSayisi = 1 | 3 | 5;

interface Config {
  retryAttempts: YenidenDenemeSayisi;
}

const config1: Config = { retryAttempts: 3 }; // Geçerli
const config2: Config = { retryAttempts: 7 }; // Hata: '{ retryAttempts: 7; }' türü, 'Config' türüne atanamaz.

Bu örnek, retryAttempts için olası değerleri belirli bir kümeyle sınırlar, bu da yapılandırmanızın netliğini ve güvenilirliğini artırır.

Boolean Literal Tipleri

Boolean literal tipleri, belirli true veya false değerlerini temsil eder. String veya sayı literal tiplerinden daha az çok yönlü görünseler de, belirli senaryolarda faydalı olabilirler.

Temel Sözdizimi

Bir boolean literal tipi tanımlamanın sözdizimi şöyledir:


type EtkinMi = true | false;

Ancak, doğrudan true | false kullanmak gereksizdir çünkü bu boolean tipine eşdeğerdir. Boolean literal tipleri, diğer tiplerle birleştirildiğinde veya koşullu tiplerde daha kullanışlıdır.

Pratik Örnekler

1. Yapılandırma ile Koşullu Mantık:

Bir fonksiyonun davranışını bir yapılandırma bayrağına göre kontrol etmek için boolean literal tiplerini kullanabilirsiniz:


interface OzellikBayraklari {
  darkMode: boolean;
  newUserFlow: boolean;
}

function uygulamayiBaslat(flags: OzellikBayraklari) {
  if (flags.darkMode) {
    // Koyu modu etkinleştir
    console.log("Koyu mod etkinleştiriliyor...");
  } else {
    // Açık modu kullan
    console.log("Açık mod kullanılıyor...");
  }

  if (flags.newUserFlow) {
    // Yeni kullanıcı akışını etkinleştir
    console.log("Yeni kullanıcı akışı etkinleştiriliyor...");
  } else {
    // Eski kullanıcı akışını kullan
    console.log("Eski kullanıcı akışı kullanılıyor...");
  }
}

uygulamayiBaslat({ darkMode: true, newUserFlow: false });

Bu örnek standart boolean tipini kullansa da, daha karmaşık davranışlar oluşturmak için bunu koşullu tiplerle (daha sonra açıklanacak) birleştirebilirsiniz.

2. Ayrıştırılmış Union'lar (Discriminated Unions):

Boolean literal tipleri, union tiplerinde ayırt edici olarak kullanılabilir. Aşağıdaki örneği düşünün:


interface BasariliSonuc {
  success: true;
  data: any;
}

interface HataSonucu {
  success: false;
  error: string;
}

type Sonuc = BasariliSonuc | HataSonucu;

function sonucuIsle(result: Sonuc) {
  if (result.success) {
    console.log("Başarı:", result.data);
  } else {
    console.error("Hata:", result.error);
  }
}

sonucuIsle({ success: true, data: { name: "John" } });
sonucuIsle({ success: false, error: "Veri çekilemedi" });

Burada, bir boolean literal tipi olan success özelliği bir ayırt edici olarak görev yapar ve TypeScript'in if ifadesi içinde result tipini daraltmasına olanak tanır.

Literal Tipleri Union Tipleriyle Birleştirme

Literal tipleri, union tipleriyle (| operatörü kullanılarak) birleştirildiğinde en güçlü hale gelir. Bu, birkaç belirli değerden birini tutabilen bir tip tanımlamanıza olanak tanır.

Pratik Örnekler

1. Bir Durum Tipi Tanımlama:


type Durum = "beklemede" | "devam ediyor" | "tamamlandı" | "başarısız";

interface Gorev {
  id: number;
  description: string;
  status: Durum;
}

const task1: Gorev = { id: 1, description: "Giriş yapmayı uygula", status: "devam ediyor" }; // Geçerli
const task2: Gorev = { id: 2, description: "Çıkış yapmayı uygula", status: "bitti" };       // Hata: '{ id: number; description: string; status: string; }' türü, 'Gorev' türüne atanamaz.

Bu örnek, bir Gorev nesnesi için izin verilen belirli bir durum değerleri kümesini nasıl zorunlu kılacağınızı gösterir.

2. Bir Cihaz Tipi Tanımlama:

Bir mobil uygulamada, farklı cihaz türlerini ele almanız gerekebilir. Bunları temsil etmek için bir string literal tipleri birliği kullanabilirsiniz:


type CihazTipi = "mobil" | "tablet" | "masaüstü";

function cihazTipiniKaydet(device: CihazTipi) {
  console.log(`Cihaz tipi: ${device}`);
}

cihazTipiniKaydet("mobil"); // Geçerli
cihazTipiniKaydet("akıllısaat"); // Hata: '"akıllısaat"' türündeki argüman, 'CihazTipi' türündeki parametreye atanamaz.

Bu örnek, cihazTipiniKaydet fonksiyonunun yalnızca geçerli cihaz tipleriyle çağrılmasını sağlar.

Literal Tipler ve Tip Takma Adları (Type Aliases)

Tip takma adları (type anahtar kelimesi kullanılarak), bir literal tipe bir ad vermenin bir yolunu sunar, bu da kodunuzu daha okunabilir ve sürdürülebilir hale getirir.

Pratik Örnekler

1. Bir Para Birimi Kodu Tipi Tanımlama:


type ParaBirimiKodu = "USD" | "EUR" | "GBP" | "JPY";

function paraBiriminiFormatla(amount: number, currency: ParaBirimiKodu): string {
  // ... tutarı para birimi koduna göre biçimlendirme uygulaması
  console.log(`${amount} tutarı ${currency} para biriminde biçimlendiriliyor`);
  return "Biçimlendirilmiş tutar"; // Yer tutucu
}

paraBiriminiFormatla(100, "USD"); // Geçerli
paraBiriminiFormatla(200, "CAD"); // Hata: '"CAD"' türündeki argüman, 'ParaBirimiKodu' türündeki parametreye atanamaz.

Bu örnek, bir dizi para birimi kodu için bir ParaBirimiKodu tip takma adı tanımlar, bu da paraBiriminiFormatla fonksiyonunun okunabilirliğini artırır.

2. Haftanın Günü Tipi Tanımlama:


type HaftaninGunu = "Pazartesi" | "Salı" | "Çarşamba" | "Perşembe" | "Cuma" | "Cumartesi" | "Pazar";

function haftaSonuMu(day: HaftaninGunu): boolean {
  return day === "Cumartesi" || day === "Pazar";
}

console.log(haftaSonuMu("Pazartesi"));   // false
console.log(haftaSonuMu("Cumartesi")); // true
console.log(haftaSonuMu("EglenceGunu"));   // Hata: '"EglenceGunu"' türündeki argüman, 'HaftaninGunu' türündeki parametreye atanamaz.

Literal Çıkarımı (Literal Inference)

TypeScript, değişkenlere atadığınız değerlere göre genellikle literal tipleri otomatik olarak çıkarabilir. Bu, özellikle const değişkenleriyle çalışırken kullanışlıdır.

Pratik Örnekler

1. String Literal Tiplerini Çıkarma:


const apiKey = "senin-api-anahtarın"; // TypeScript, apiKey'in tipini "senin-api-anahtarın" olarak çıkarır

function apiKeyDogrula(key: "senin-api-anahtarın") {
  return key === "senin-api-anahtarın";
}

console.log(apiKeyDogrula(apiKey)); // true

const baskaAnahtar = "gecersiz-anahtar";
console.log(apiKeyDogrula(baskaAnahtar)); // Hata: 'string' türündeki argüman, '"senin-api-anahtarın"' türündeki parametreye atanamaz.

Bu örnekte, TypeScript apiKey'in tipini string literal tipi olan "senin-api-anahtarın" olarak çıkarır. Ancak, bir değişkene sabit olmayan bir değer atarsanız, TypeScript genellikle daha geniş olan string tipini çıkaracaktır.

2. Sayı Literal Tiplerini Çıkarma:


const port = 8080; // TypeScript, port'un tipini 8080 olarak çıkarır

function sunucuyuBaslat(portNumber: 8080) {
  console.log(`Sunucu ${portNumber} portunda başlatılıyor`);
}

sunucuyuBaslat(port); // Geçerli

const baskaPort = 3000;
sunucuyuBaslat(baskaPort); // Hata: 'number' türündeki argüman, '8080' türündeki parametreye atanamaz.

Literal Tipleri Koşullu Tiplerle Kullanma

Literal tipleri, koşullu tiplerle birleştirildiğinde daha da güçlü hale gelir. Koşullu tipler, diğer tiplere bağlı tipler tanımlamanıza olanak tanır, bu da çok esnek ve ifade gücü yüksek tip sistemleri oluşturur.

Temel Sözdizimi

Koşullu bir tipin sözdizimi şöyledir:


TipA extends TipB ? TipC : TipD

Bu şu anlama gelir: eğer TipA, TipB'ye atanabilirse, sonuçta ortaya çıkan tip TipC'dir; aksi takdirde, sonuçta ortaya çıkan tip TipD'dir.

Pratik Örnekler

1. Durumu Mesajla Eşleştirme:


type Durum = "beklemede" | "devam ediyor" | "tamamlandı" | "başarısız";

type DurumMesaji = T extends "beklemede"
  ? "Eylem bekleniyor"
  : T extends "devam ediyor"
  ? "Şu anda işleniyor"
  : T extends "tamamlandı"
  ? "Görev başarıyla tamamlandı"
  : "Bir hata oluştu";

function durumMesajiAl(status: T): DurumMesaji {
  switch (status) {
    case "beklemede":
      return "Eylem bekleniyor" as DurumMesaji;
    case "devam ediyor":
      return "Şu anda işleniyor" as DurumMesaji;
    case "tamamlandı":
      return "Görev başarıyla tamamlandı" as DurumMesaji;
    case "başarısız":
      return "Bir hata oluştu" as DurumMesaji;
    default:
      throw new Error("Geçersiz durum");
  }
}

console.log(durumMesajiAl("beklemede"));    // Eylem bekleniyor
console.log(durumMesajiAl("devam ediyor")); // Şu anda işleniyor
console.log(durumMesajiAl("tamamlandı"));   // Görev başarıyla tamamlandı
console.log(durumMesajiAl("başarısız"));      // Bir hata oluştu

Bu örnek, her olası durumu karşılık gelen bir mesajla eşleştiren bir DurumMesaji tipi tanımlar. durumMesajiAl fonksiyonu, tip güvenli durum mesajları sağlamak için bu tipten yararlanır.

2. Tip Güvenli Bir Olay İşleyici Oluşturma:


type OlayTipi = "click" | "mouseover" | "keydown";

type OlayVerisi = T extends "click"
  ? { x: number; y: number; } // Tıklama olayı verisi
  : T extends "mouseover"
  ? { target: HTMLElement; }   // Fareyle üzerine gelme olayı verisi
  : { key: string; }             // Tuşa basma olayı verisi

function olayiIsle(type: T, data: OlayVerisi) {
  console.log(`${type} olay türü şu verilerle işleniyor:`, data);
}

olayiIsle("click", { x: 10, y: 20 }); // Geçerli
olayiIsle("mouseover", { target: document.getElementById("myElement")! }); // Geçerli
olayiIsle("keydown", { key: "Enter" }); // Geçerli

olayiIsle("click", { key: "Enter" }); // Hata: '{ key: string; }' türündeki argüman, '{ x: number; y: number; }' türündeki parametreye atanamaz.

Bu örnek, olay türüne göre farklı veri yapıları tanımlayan bir OlayVerisi tipi oluşturur. Bu, her olay türü için olayiIsle fonksiyonuna doğru verinin geçirilmesini sağlamanıza olanak tanır.

Literal Tipleri Kullanmak İçin En İyi Uygulamalar

TypeScript projelerinizde literal tipleri etkili bir şekilde kullanmak için aşağıdaki en iyi uygulamaları göz önünde bulundurun:

Literal Tipleri Kullanmanın Faydaları

Sonuç

TypeScript literal tipleri, katı değer kısıtlamaları uygulamanıza, kod netliğini artırmanıza ve hataları önlemenize olanak tanıyan güçlü bir özelliktir. Sözdizimini, kullanımını ve faydalarını anlayarak, daha sağlam ve sürdürülebilir TypeScript uygulamaları oluşturmak için literal tiplerden yararlanabilirsiniz. Renk paletleri ve API uç noktaları tanımlamaktan farklı dilleri ele almaya ve tip güvenli olay işleyicileri oluşturmaya kadar, literal tipler geliştirme iş akışınızı önemli ölçüde geliştirebilecek geniş bir pratik uygulama yelpazesi sunar.

TypeScript Literal Tipleri: Kesin Değer Kısıtlamalarında Uzmanlaşma | MLOG